# Check requisite packages are installed.
There were 36 warnings (use warnings() to see them)
packages <- c(
  "plotly", 
  "dplyr"
)
for (pkg in packages) {
  library(pkg, character.only = TRUE)
}

Tabs

Load

Pulling code almost directly from LM1996-NumPoolComScaling-Results-2021-05.Rmd.

dirViking <- c(
  file.path(
    getwd(), "LCAB_LawMorton1996-NumericalPoolCommunityScaling9"
  ),
  file.path(
    getwd(), "LCAB_LawMorton1996-NumericalPoolCommunityScaling10"
  )
)
dirVikingResults <- file.path(
  dirViking, c("save-2021-08-03") # Latter not 100% yet.
)
resultFormat <- paste0(
  "run-", 
  "%d", # Combination Number, or CombnNum.
  "-", 
  "%s", # Run Seed.
  ".RDS"
)
source(
  file.path(getwd(), 
            "LawMorton1996-NumericalPoolCommunityScaling-Settings9.R")
)

paramFrame <- with(list(
  b = rep(basal, times = length(consumer)),
  c = rep(consumer, each = length(basal)),
  s1 = seedsPrep[1:(length(basal) * length(consumer))],
  s2 = seedsPrep[
    (length(basal) * length(consumer) + 1):(
      2 * length(basal) * length(consumer))
  ],
  sR = seedsRun
), {
  temp <- data.frame(
    CombnNum = 0,
    Basals = b,
    Consumers = c,
    SeedPool = s1,
    SeedMat = s2,
    SeedRuns = "",
    SeedRunsNum = 0,
    EndStates = I(rep(list(""), length(b))),
    EndStatesNum = 0,
    EndStateSizes = I(rep(list(""), length(b))),
    EndStateSizesNum = NA,
    EndStateAssembly = I(rep(list(""), length(b))),
    EndStateAbundance = I(rep(list(""), length(b))),
    Dataset = "Viking9",
    DatasetID = 1,
    stringsAsFactors = FALSE
  )
  for (i in 1:nrow(temp)) {
    seeds <- sR[((i - 1) * runs + 1) : (i * runs)]
    temp$SeedRuns[i] <- toString(seeds) # CSV
    temp$SeedRunsNum[i] <- length(seeds)
  }
  temp$CombnNum <- 1:nrow(temp)
  temp
})
# Note: n + 2 end states. Failure to finish, failure to obtain state, and state.
for (i in 1:nrow(paramFrame)) {
  resultsList <- list(
    "No Run" = 0,
    "No State" = 0
  )
  resultsSize <- list(
    "0" = 0
  )
  resultsAssembly <- list(
    "No Run" = data.frame(),
    "No State" = data.frame()
  )
  resultsAbund <- list(
    "No Run" = "",
    "No State" = ""
  )
  seeds <- unlist(strsplit(paramFrame$SeedRuns[i], ', '))
  for (seed in seeds) {
    fileName <- file.path(
      dirVikingResults[paramFrame$DatasetID[i]],
      sprintf(resultFormat, paramFrame$CombnNum[i], seed)
    )
    
    if (file.exists(fileName)) {
      temp <- load(fileName)
      temp <- eval(parse(text = temp)) # Get objects.
      
      if (is.list(temp) && "Result" %in% names(temp)) {
        
        if (is.data.frame(temp$Result))
          community <- temp$Result$Community[[nrow(temp$Result)]]
        else 
          community <- temp$Result
        
        size <- toString(length(community))
        
        if (community[1] != "") 
          abund <- toString(temp$Abund[community + 1])
        else 
          abund <- ""
        
        community <- toString(community)
        
        if (community == "") {
          resultsList$`No State` <- resultsList$`No State` + 1
          resultsSize$`0` <- resultsSize$`0` + 1
          
        } else if (community %in% names(resultsList)) {
          resultsList[[community]] <- resultsList[[community]] + 1
          resultsSize[[size]] <- resultsSize[[size]] + 1
          
        } else {
          resultsList[[community]] <- 1
          resultsAssembly[[community]] <- temp
          resultsAbund[[community]] <- abund
          
          if (size %in% resultsSize) {
            resultsSize[[size]] <- resultsSize[[size]] + 1
          } else {
            resultsSize[[size]] <- 1
          }
        }
      } else {
        resultsList$`No State` <- resultsList$`No State` + 1
        resultsSize$`0` <- resultsSize$`0` + 1
      }
    } else {
      resultsList$`No Run` <- resultsList$`No Run` + 1
      resultsSize$`0` <- resultsSize$`0` + 1
    }
  }
  
  paramFrame$EndStates[[i]] <- resultsList
  paramFrame$EndStatesNum[i] <- length(resultsList) - 2 # ! No State, No Run
  paramFrame$EndStateSizes[[i]] <- resultsSize
  paramFrame$EndStateSizesNum[i] <- length(resultsSize) - 1 # ! 0
  paramFrame$EndStateAssembly[[i]] <- resultsAssembly
  paramFrame$EndStateAbundance[[i]] <- resultsAbund
}
source(
  file.path(getwd(), 
            "LawMorton1996-NumericalPoolCommunityScaling-Settings10.R")
)

oldNrow <- nrow(paramFrame)

paramFrame <- rbind(paramFrame, with(list(
  b = rep(basal, times = length(consumer)),
  c = rep(consumer, each = length(basal)),
  s1 = seedsPrep[1:(length(basal) * length(consumer))],
  s2 = seedsPrep[
    (length(basal) * length(consumer) + 1):(
      2 * length(basal) * length(consumer))
  ],
  sR = seedsRun
), {
  temp <- data.frame(
    CombnNum = 0,
    Basals = b,
    Consumers = c,
    SeedPool = s1,
    SeedMat = s2,
    SeedRuns = "",
    SeedRunsNum = 0,
    EndStates = I(rep(list(""), length(b))),
    EndStatesNum = 0,
    EndStateSizes = I(rep(list(""), length(b))),
    EndStateSizesNum = NA,
    EndStateAssembly = I(rep(list(""), length(b))),
    EndStateAbundance = I(rep(list(""), length(b))),
    Dataset = "Viking10",
    DatasetID = 2,
    stringsAsFactors = FALSE
  )
  for (i in 1:nrow(temp)) {
    seeds <- sR[((i - 1) * runs + 1) : (i * runs)]
    temp$SeedRuns[i] <- toString(seeds) # CSV
    temp$SeedRunsNum[i] <- length(seeds)
  }
  temp$CombnNum <- 1:nrow(temp)
  temp
})
)
# Note: n + 2 end states. Failure to finish, failure to obtain state, and state.
# Modified from above, but with the abundance recorded.
for (i in (oldNrow + 1):nrow(paramFrame)) {
  resultsList <- list(
    "No Run" = 0,
    "No State" = 0
  )
  resultsSize <- list(
    "0" = 0
  )
  resultsAssembly <- list(
    "No Run" = data.frame(),
    "No State" = data.frame()
  )
  resultsAbund <- list(
    "No Run" = "",
    "No State" = ""
  )
  seeds <- unlist(strsplit(paramFrame$SeedRuns[i], ', '))
  for (seed in seeds) {
    fileName <- file.path(
      dirVikingResults[paramFrame$DatasetID[i]],
      sprintf(resultFormat, paramFrame$CombnNum[i], seed)
    )
    
    if (file.exists(fileName)) {
      temp <- load(fileName)
      temp <- eval(parse(text = temp)) # Get objects.
      
      if (is.list(temp) && "Result" %in% names(temp)) {
        
        if (is.data.frame(temp$Result))
          community <- temp$Result$Community[[nrow(temp$Result)]]
        else 
          community <- temp$Result
        
        size <- toString(length(community))
        
        if (community[1] != "") 
          abund <- toString(temp$Abund[community + 1])
        else 
          abund <- ""
        
        community <- toString(community)
        
        if (community == "") {
          resultsList$`No State` <- resultsList$`No State` + 1
          resultsSize$`0` <- resultsSize$`0` + 1
          
        } else if (community %in% names(resultsList)) {
          resultsList[[community]] <- resultsList[[community]] + 1
          resultsSize[[size]] <- resultsSize[[size]] + 1
          
        } else {
          resultsList[[community]] <- 1
          resultsAssembly[[community]] <- temp
          resultsAbund[[community]] <- abund
          
          if (size %in% resultsSize) {
            resultsSize[[size]] <- resultsSize[[size]] + 1
          } else {
            resultsSize[[size]] <- 1
          }
        }
      } else {
        resultsList$`No State` <- resultsList$`No State` + 1
        resultsSize$`0` <- resultsSize$`0` + 1
      }
    } else {
      resultsList$`No Run` <- resultsList$`No Run` + 1
      resultsSize$`0` <- resultsSize$`0` + 1
    }
  }
  
  paramFrame$EndStates[[i]] <- resultsList
  paramFrame$EndStatesNum[i] <- length(resultsList) - 2 # ! No State, No Run
  paramFrame$EndStateSizes[[i]] <- resultsSize
  paramFrame$EndStateSizesNum[i] <- length(resultsSize) - 1 # ! 0
  paramFrame$EndStateAssembly[[i]] <- resultsAssembly
  paramFrame$EndStateAbundance[[i]] <- resultsAbund
}

Plot Preparation

# X, Y, Basal and Consumer.
# Z = Sizes of the Endstates.

plotScalingData <- data.frame(
  CombnNum = rep(paramFrame$CombnNum, paramFrame$EndStatesNum),
  Basals = rep(paramFrame$Basals, paramFrame$EndStatesNum),
  Consumers = rep(paramFrame$Consumers, paramFrame$EndStatesNum),
  Dataset = rep(paramFrame$Dataset, paramFrame$EndStatesNum),
  DatasetID = rep(paramFrame$DatasetID, paramFrame$EndStatesNum)
)

# Communities
comms <- unlist(lapply(paramFrame$EndStates, names))
freqs <- unlist(paramFrame$EndStates)
asmbl <- unlist(paramFrame$EndStateAssembly, recursive = FALSE)
asmbl <- asmbl[comms != "No Run" & comms != "No State"]
freqs <- freqs[comms != "No Run" & comms != "No State"]
comms <- comms[comms != "No Run" & comms != "No State"]

asmbl <- lapply(asmbl, function(d) {
  if (is.null(d)) return(NA)
  if ("Result.Outcome" %in% names(d))
    d %>% dplyr::filter(Result.Outcome != "Type 1 (Failure)" & 
                          Result.Outcome != "Present")
  else
    d$Result %>% dplyr::filter(Outcome != "Type 1 (Failure)" & 
                                 Outcome != "Present")
})

plotScalingData$Communities <- comms
plotScalingData$CommunityFreq <- freqs
plotScalingData$CommunitySeq <- asmbl

# Community Size
temp <- unlist(lapply(strsplit(plotScalingData$Communities, ','), length))
plotScalingData$CommunitySize <- temp

candidateData <- plotScalingData %>% dplyr::group_by(
  CombnNum, Dataset
) %>% dplyr::mutate(
  OtherSteadyStates = dplyr::n() - 1
)

Pools and Matrices

mats <- list()
poolsall <- list() # name pools used in save data; be careful!

for (i in 1:length(dirViking)) {
  temp <- load(file.path(
    dirViking[i], 
    paste0("LawMorton1996-NumericalPoolCommunityScaling-PoolMats", 
           c(9, 10)[i], 
           ".RDS")
  ))
  mats[[i]] <- eval(parse(text = temp[1]))
  poolsall[[i]] <- eval(parse(text = temp[2]))
}
pools <- poolsall

Abundances

# First, check if it is in the paramFrame.
# Second, check if it is in the saved data from the previous.
# Otherwise, ignore it, we'll figure out what it is and why it is missing later.

candidateData$CommunityAbund <- ""

for (r in 1:nrow(candidateData)) {
  # ID 1:4 are used to identify paramFrame, 5 used to identify abundance
  ID <- candidateData[r, 1:6]
  paramFrameRow <- paramFrame %>% dplyr::filter(
    CombnNum == ID$CombnNum,
    Basals == ID$Basals,
    Consumers == ID$Consumers,
    Dataset == ID$Dataset
  )
  
  if (is.list(paramFrameRow$EndStateAbundance[[1]])) {
    entry <- which(ID$Communities == names(paramFrameRow$EndStateAbundance[[1]]))
    if (length(entry)) {
      candidateData$CommunityAbund[r] <- paramFrameRow$EndStateAbundance[[1]][[entry]]
      next()
    }
  }
}
print(paste("Failures:", 
            sum(candidateData$CommunityAbund %in% 
                  c("", "Failure", "EstimatedFailure"))))
[1] "Failures: 0"
candidateData <- candidateData %>% dplyr::filter(CommunityAbund != "",
                                                 CommunityAbund != "Failure",
                                                 CommunityAbund != "EstimateFailure")
candidateData$CommunityProd <- NA
for (r in 1:nrow(candidateData)) {
  candidateData$CommunityProd[r] <- with(
    candidateData[r, ], 
    RMTRCode2::Productivity(
      Pool = pools[[DatasetID]][[CombnNum]], 
      InteractionMatrix = mats[[DatasetID]][[CombnNum]], 
      Community = Communities, 
      Populations = CommunityAbund
    )
  )
}
print(paste("Numerically Unstable:", 
            sum(candidateData$CommunityProd > 10^10 
                  )))
[1] "Numerically Unstable: 7"
candidateData <- candidateData %>% dplyr::filter(CommunityProd < 10^10)

Communities

# For usage by the reader.

plotScaling <- plotly::plot_ly(
  candidateData,
  x = ~Basals,
  y = ~Consumers,
  z = ~CommunitySize,
  color = ~Dataset,
  colors = c("red", "blue", "black")
)

plotScaling <- plotly::add_markers(plotScaling)

plotScaling <- plotly::layout(
  plotScaling,
  scene = list(
    xaxis = list(type = "log"),
    yaxis = list(type = "log"),
    camera = list(
      eye = list(
        x = -1.25, y = -1.25, z = .05
      )
    )
  )
)

plotScaling

Communities Data

candidateData
There were 50 or more warnings (use warnings() to see the first 50)

Foodwebs, Prep

foodWebs <- list()

for (r in 1:nrow(candidateData)) {
  foodWebs[[r]] <- with(
    candidateData[r, ],
    {
      redCom <- RMTRCode2::CsvRowSplit(Communities)
      redMat <- mats[[DatasetID]][[CombnNum]][redCom, redCom]
      redPool <- pools[[DatasetID]][[CombnNum]][redCom, ]
      
      colnames(redMat) <- paste0('s',as.character(redCom))
      rownames(redMat) <- colnames(redMat)
      
      names(redPool)[1] <- "node"
      redPool$node <- colnames(redMat)
      names(redPool)[3] <- "M"
      
      Graph <- igraph::graph_from_adjacency_matrix(
        redMat, weighted = TRUE
      )
      
      Graph <- igraph::set.vertex.attribute(
        Graph, "name", value = colnames(redMat)
      )
      
      redPool$N <- RMTRCode2::CsvRowSplit(CommunityAbund)
      
      # For later analysis, take the matrix diagonal.
      
      redPool$Intraspecific <- diag(redMat)
      
      GraphAsDataFrame <- igraph::as_data_frame(Graph)
  
      # Add in abundances for calculating abundance * (gain or loss)
      GraphAsDataFrame <- dplyr::left_join(
        GraphAsDataFrame,
        dplyr::select(redPool, node, N),
        by = c("to" = "node")
      )
  
      # Split data frame.
      ResCon <- GraphAsDataFrame[GraphAsDataFrame$weight > 0,]
      ConRes <- GraphAsDataFrame[GraphAsDataFrame$weight < 0,]
      
      # Reorder and rename variables.
      ResCon <- dplyr::select(ResCon, 
                                 to, from, # resource = to, consumer = from, 
                                 effectPerUnit = weight, resourceAbund = N)
      ConRes <- dplyr::select(ConRes, 
                                 to, from, # resource = from, consumer = to, 
                                 effectPerUnit = weight, consumerAbund = N)
      ResCon <- dplyr::mutate(dplyr::group_by(ResCon, from),
                              effectActual = effectPerUnit * resourceAbund,
                              Type = "Exploit+")
      ConRes <- dplyr::mutate(dplyr::group_by(ConRes, from),
                              effectActual = effectPerUnit * consumerAbund,
                              Type = ifelse(from == to,
                                            "SelfReg-",
                                            "Exploit-"))
      
      IntriG <- with(redPool, data.frame(
                              from = node, #resource = node,
                              to = node, #consumer = node,
                              effectPerUnit = ifelse(ReproductionRate > 0,
                                                   ReproductionRate, 0),
                              effectActual = ifelse(ReproductionRate > 0,
                                                  N * ReproductionRate, 0),
                              Type = "Intrisc+")) 
      IntriL <- with(redPool, data.frame(
                              from = node, #resource = node,
                              to = node, #consumer = node,
                              effectPerUnit = ifelse(ReproductionRate < 0,
                                                   ReproductionRate, 0),
                              effectActual = ifelse(ReproductionRate < 0,
                                                  N * ReproductionRate, 0),
                              Type = "Intrisc-"))
      
      EdgeDataFrame <- dplyr::bind_rows(
        dplyr::select(ResCon, -resourceAbund), 
        dplyr::select(ConRes, -consumerAbund),
        IntriG, IntriL
      )
      
      EdgeDataFrame <- EdgeDataFrame %>% dplyr::rename(
        # Empirically speaking, to and from appear reversed.
        # A consumer (from) should have a negative effect on resource (to),
        # but the organisation so far marks it as positive. We fix this.
        tempname = to,
        to = from
      ) %>% dplyr::rename(
        from = tempname
      ) %>% dplyr::filter(
        # Remove placeholder entries
        effectPerUnit != 0
      ) %>% dplyr::mutate(
        # Useful to keep effects separate
        effectSign = sign(effectPerUnit)
      ) %>% group_by(
        to, effectSign
      ) %>% dplyr::mutate(
        # Perform the post mortem of the most influential from's
        effectEfficiency = effectPerUnit / sum(effectPerUnit), 
        effectNormalised = effectActual / sum(effectActual)
      ) %>% dplyr::arrange(to)
      
      list(
        Edges = EdgeDataFrame,
        Vertices = redPool
      )
    }
  )
}
toCheddar <- function(EVList, name = "") {# Edges Vertices List
  links <- EVList$Edges

  # cheddar does not like "cannibalism".
  links <- links[
    links$to != links$from,
  ]

  # "[C]olumns called ‘resource’ and ‘consumer’ must be given."
  links <- dplyr::bind_rows(
    links %>% dplyr::filter(effectSign == 1) %>% dplyr::rename(
      resource = from, consumer = to),
    links %>% dplyr::filter(effectSign == -1) %>% dplyr::rename(
      resource = to, consumer = from),
  ) %>% dplyr::select(-Type) # Cheddar confuses node Type and edge Type.

  cheddar::Community(
    nodes = EVList$Vertices,
    properties = list(
      title = name,
      M.units = "masses",
      N.units = "abund"
    ),
    trophic.links = links
  )
}

toIGraph <- function(EVList, sign = 0) {
  igraph::graph_from_data_frame(
    d = if(sign == 0) {
      EVList$Edges
    } else {
      EVList$Edges[EVList$Edges$effectSign == sign, ]
    },
    directed = TRUE,
    vertices = EVList$Vertices
  )
}


toPostMortem <- function(EVList,
                         threshold = 0, # sets to minimal size edges below
                         nodeSize = c("None", "Abundance", "Size"),
                         edgeScale = 10,
                         reducedTrophic = TRUE) {
  if (tolower(threshold) == "adaptive") {
    threshold = EVList$Edges %>% group_by(
      to, effectSign
    ) %>% summarise(
      max = max(effectNormalised), .groups = "drop"
    ) %>% ungroup %>% pull(max) %>% min
  }

  theGc <- toCheddar(EVList, name = "Trophic Levels")
  theGi <- toIGraph(EVList)

  theGiGain <- toIGraph(EVList, sign = 1)
  theGiLoss <- toIGraph(EVList, sign = -1)

  theLayout <- igraph::layout.circle(theGi)

  theSize <- match.arg(nodeSize, c("Abundance", "Size", "None"))
  if (theSize == "Abundance")
    theVs <- sqrt(igraph::vertex_attr(theGi)$N) * 10
  else if (theSize == "Size") {
    theVs <- igraph::vertex_attr(theGi)$M
    theVs <- sqrt(theVs / min(theVs)) * 10
  } else if (theSize == "None") {
    theVs <- 15
  }

  theColors <- ifelse(
    igraph::vertex_attr(theGi)$Type == "Basal", "skyblue", "red"
  )
  if ("Core" %in% names(igraph::vertex_attr(theGi))) {
    theShapes <- ifelse(igraph::vertex_attr(theGi)$Core,
                        0,
                        1)
  } else {
    theShapes <- 1 
    # Note Igraph uses "circle" then "rectangle",
    # but R and cheddar use "rectangle" then "circle", so we will use a !.
  }

  theBoth <- igraph::edge_attr(theGi)$effectNormalised
  theGain <- igraph::edge_attr(theGiGain)$effectNormalised
  theLoss <- igraph::edge_attr(theGiLoss)$effectNormalised

  theBoth[theBoth < threshold] <- 0
  theGain[theGain < threshold] <- 0
  theLoss[theLoss < threshold] <- 0

  # Inform the graphs of which edges are not needed.
  theGi <- igraph::delete_edges(theGi, which(theBoth == 0))
  theGiGain <- igraph::delete_edges(theGiGain, which(theGain == 0))
  theGiLoss <- igraph::delete_edges(theGiLoss, which(theLoss == 0))

  # Remove the same entries so that lengths match.
  theGain <- theGain[theGain > 0]
  theLoss <- theLoss[theLoss > 0]

  theGain <- theGain * edgeScale
  theLoss <- theLoss * edgeScale

  parold <- par(no.readonly = TRUE)
  par(mfrow = c(2, 2), # Two Rows, Two Columns
      mar = c(0, 1.5, 1, 0), # Margins, bottom, left, top, right
      oma = c(0.1, 0.1, 0.1, 0.1) # Outer margins.
  )

  cheddar::PlotWebByLevel(
    theGc,
    show.level.lines = TRUE,
    # Had been using LongWeighted, but that seems to give the upside down T.
    # Flow based seems to be more what we are expecting, given the usage of
    # thresholding and what that shows. The flows here are expected to be
    # flows of energy through the food web.
    level = cheddar::FlowBasedTrophicLevel(theGc, weight.by = "effectNormalised"),
      col = theColors,
      pch = theShapes
  )

  if (!reducedTrophic) {
    plot(
      theGi,
      layout = theLayout,
      vertex.size = theVs,
      edge.width = 1,
      edge.arrow.size = 0.3,
      edge.arrow.width = 1,
      vertex.color = theColors,
      vertex.shape = igraph::shapes()[as.numeric(!theShapes) + 1],
      edge.lty = 2,
      edge.color = "grey",
      edge.arrow.mode = ">",
      main = "Consumption"
    )
  } else {
    EVListRed <- EVList
    EVListRed$Edges <- EVListRed$Edges %>% dplyr::filter(
      effectNormalised >= threshold
    )
    theGc2 <- toCheddar(EVListRed, name = "Strongest Trophic Levels")
    cheddar::PlotWebByLevel(
      theGc2,
      show.level.lines = TRUE,
    level = cheddar::FlowBasedTrophicLevel(theGc2, weight.by = "effectNormalised"),
      col = theColors,
      pch = theShapes
    )
  }

  plot(
    theGiGain,
    layout = theLayout,
    vertex.size = theVs,
    edge.width = theGain,
    edge.arrow.size = 0.3,
    edge.arrow.width = 1,
    vertex.color = theColors,
      vertex.shape = igraph::shapes()[as.numeric(!theShapes) + 1],
    edge.lty = 2,
    edge.color = "blue",
    edge.arrow.mode = ">",
    main = "Consumer's Gains"
  )

  plot(
    theGiLoss,
    layout = theLayout,
    vertex.size = theVs,
    edge.width = theLoss,
    edge.arrow.size = 0.3,
    edge.arrow.width = 2,
    vertex.color = theColors,
      vertex.shape = igraph::shapes()[as.numeric(!theShapes) + 1],
    edge.lty = 3,
    edge.color = "darkred",
    edge.arrow.mode = "<",
    main = "Resource's Losses"
  )
  
  par(parold)
  
  EVList$Edges %>% dplyr::ungroup() %>% dplyr::filter(
    effectNormalised >= threshold
  ) %>% dplyr::select(
    -effectSign
  ) %>% dplyr::arrange(
    to, -effectNormalised
  )
}

Foodwebs, Overlapping

1

i <- 1
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

2

i <- 2
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

3

i <- 3
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

4

i <- 4
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

5

i <- 5
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

6

i <- 6
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

7

i <- 7
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

8

i <- 8
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

Foodwebs, Larger Food Preference

9

i <- 9
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

10

i <- 10
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

11

i <- 11
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

12

i <- 12
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

13

i <- 13
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

14

i <- 14
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

15

i <- 15
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

16

i <- 16
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

17

i <- 17
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

18

i <- 18
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp

19

i <- 19
toPostMortem(foodWebs[[i]], nodeSize = "None", threshold = "Adaptive") -> temp

temp
LS0tDQp0aXRsZTogIkFuc3dlcmluZyBRdWVzdGlvbnM7IEdhdGhlciBEYXRhLCBWaWtpbmcgOToxMCwgMjAyMS0wOCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCi0tLQ0KDQpgYGB7ciBsaWJzLCBtZXNzYWdlPUZBTFNFfQ0KIyBDaGVjayByZXF1aXNpdGUgcGFja2FnZXMgYXJlIGluc3RhbGxlZC4NCnBhY2thZ2VzIDwtIGMoDQogICJwbG90bHkiLCANCiAgImRwbHlyIg0KKQ0KZm9yIChwa2cgaW4gcGFja2FnZXMpIHsNCiAgbGlicmFyeShwa2csIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCn0NCmBgYA0KDQojIFRhYnMgey50YWJzZXR9DQoNCiMjIExvYWQNClB1bGxpbmcgY29kZSBhbG1vc3QgZGlyZWN0bHkgZnJvbSBgTE0xOTk2LU51bVBvb2xDb21TY2FsaW5nLVJlc3VsdHMtMjAyMS0wNS5SbWRgLg0KYGBge3IgZGlyc30NCmRpclZpa2luZyA8LSBjKA0KICBmaWxlLnBhdGgoDQogICAgZ2V0d2QoKSwgIkxDQUJfTGF3TW9ydG9uMTk5Ni1OdW1lcmljYWxQb29sQ29tbXVuaXR5U2NhbGluZzkiDQogICksDQogIGZpbGUucGF0aCgNCiAgICBnZXR3ZCgpLCAiTENBQl9MYXdNb3J0b24xOTk2LU51bWVyaWNhbFBvb2xDb21tdW5pdHlTY2FsaW5nMTAiDQogICkNCikNCmRpclZpa2luZ1Jlc3VsdHMgPC0gZmlsZS5wYXRoKA0KICBkaXJWaWtpbmcsIGMoInNhdmUtMjAyMS0wOC0wMyIpICMgTGF0dGVyIG5vdCAxMDAlIHlldC4NCikNCnJlc3VsdEZvcm1hdCA8LSBwYXN0ZTAoDQogICJydW4tIiwgDQogICIlZCIsICMgQ29tYmluYXRpb24gTnVtYmVyLCBvciBDb21ibk51bS4NCiAgIi0iLCANCiAgIiVzIiwgIyBSdW4gU2VlZC4NCiAgIi5SRFMiDQopDQpgYGANCg0KYGBge3Igb3JnYW5pc2VQYXJhbXN9DQpzb3VyY2UoDQogIGZpbGUucGF0aChnZXR3ZCgpLCANCiAgICAgICAgICAgICJMYXdNb3J0b24xOTk2LU51bWVyaWNhbFBvb2xDb21tdW5pdHlTY2FsaW5nLVNldHRpbmdzOS5SIikNCikNCg0KcGFyYW1GcmFtZSA8LSB3aXRoKGxpc3QoDQogIGIgPSByZXAoYmFzYWwsIHRpbWVzID0gbGVuZ3RoKGNvbnN1bWVyKSksDQogIGMgPSByZXAoY29uc3VtZXIsIGVhY2ggPSBsZW5ndGgoYmFzYWwpKSwNCiAgczEgPSBzZWVkc1ByZXBbMToobGVuZ3RoKGJhc2FsKSAqIGxlbmd0aChjb25zdW1lcikpXSwNCiAgczIgPSBzZWVkc1ByZXBbDQogICAgKGxlbmd0aChiYXNhbCkgKiBsZW5ndGgoY29uc3VtZXIpICsgMSk6KA0KICAgICAgMiAqIGxlbmd0aChiYXNhbCkgKiBsZW5ndGgoY29uc3VtZXIpKQ0KICBdLA0KICBzUiA9IHNlZWRzUnVuDQopLCB7DQogIHRlbXAgPC0gZGF0YS5mcmFtZSgNCiAgICBDb21ibk51bSA9IDAsDQogICAgQmFzYWxzID0gYiwNCiAgICBDb25zdW1lcnMgPSBjLA0KICAgIFNlZWRQb29sID0gczEsDQogICAgU2VlZE1hdCA9IHMyLA0KICAgIFNlZWRSdW5zID0gIiIsDQogICAgU2VlZFJ1bnNOdW0gPSAwLA0KICAgIEVuZFN0YXRlcyA9IEkocmVwKGxpc3QoIiIpLCBsZW5ndGgoYikpKSwNCiAgICBFbmRTdGF0ZXNOdW0gPSAwLA0KICAgIEVuZFN0YXRlU2l6ZXMgPSBJKHJlcChsaXN0KCIiKSwgbGVuZ3RoKGIpKSksDQogICAgRW5kU3RhdGVTaXplc051bSA9IE5BLA0KICAgIEVuZFN0YXRlQXNzZW1ibHkgPSBJKHJlcChsaXN0KCIiKSwgbGVuZ3RoKGIpKSksDQogICAgRW5kU3RhdGVBYnVuZGFuY2UgPSBJKHJlcChsaXN0KCIiKSwgbGVuZ3RoKGIpKSksDQogICAgRGF0YXNldCA9ICJWaWtpbmc5IiwNCiAgICBEYXRhc2V0SUQgPSAxLA0KICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KICApDQogIGZvciAoaSBpbiAxOm5yb3codGVtcCkpIHsNCiAgICBzZWVkcyA8LSBzUlsoKGkgLSAxKSAqIHJ1bnMgKyAxKSA6IChpICogcnVucyldDQogICAgdGVtcCRTZWVkUnVuc1tpXSA8LSB0b1N0cmluZyhzZWVkcykgIyBDU1YNCiAgICB0ZW1wJFNlZWRSdW5zTnVtW2ldIDwtIGxlbmd0aChzZWVkcykNCiAgfQ0KICB0ZW1wJENvbWJuTnVtIDwtIDE6bnJvdyh0ZW1wKQ0KICB0ZW1wDQp9KQ0KYGBgDQoNCmBgYHtyIGxvYWRSZXN1bHRzfQ0KIyBOb3RlOiBuICsgMiBlbmQgc3RhdGVzLiBGYWlsdXJlIHRvIGZpbmlzaCwgZmFpbHVyZSB0byBvYnRhaW4gc3RhdGUsIGFuZCBzdGF0ZS4NCmZvciAoaSBpbiAxOm5yb3cocGFyYW1GcmFtZSkpIHsNCiAgcmVzdWx0c0xpc3QgPC0gbGlzdCgNCiAgICAiTm8gUnVuIiA9IDAsDQogICAgIk5vIFN0YXRlIiA9IDANCiAgKQ0KICByZXN1bHRzU2l6ZSA8LSBsaXN0KA0KICAgICIwIiA9IDANCiAgKQ0KICByZXN1bHRzQXNzZW1ibHkgPC0gbGlzdCgNCiAgICAiTm8gUnVuIiA9IGRhdGEuZnJhbWUoKSwNCiAgICAiTm8gU3RhdGUiID0gZGF0YS5mcmFtZSgpDQogICkNCiAgcmVzdWx0c0FidW5kIDwtIGxpc3QoDQogICAgIk5vIFJ1biIgPSAiIiwNCiAgICAiTm8gU3RhdGUiID0gIiINCiAgKQ0KICBzZWVkcyA8LSB1bmxpc3Qoc3Ryc3BsaXQocGFyYW1GcmFtZSRTZWVkUnVuc1tpXSwgJywgJykpDQogIGZvciAoc2VlZCBpbiBzZWVkcykgew0KICAgIGZpbGVOYW1lIDwtIGZpbGUucGF0aCgNCiAgICAgIGRpclZpa2luZ1Jlc3VsdHNbcGFyYW1GcmFtZSREYXRhc2V0SURbaV1dLA0KICAgICAgc3ByaW50ZihyZXN1bHRGb3JtYXQsIHBhcmFtRnJhbWUkQ29tYm5OdW1baV0sIHNlZWQpDQogICAgKQ0KICAgIA0KICAgIGlmIChmaWxlLmV4aXN0cyhmaWxlTmFtZSkpIHsNCiAgICAgIHRlbXAgPC0gbG9hZChmaWxlTmFtZSkNCiAgICAgIHRlbXAgPC0gZXZhbChwYXJzZSh0ZXh0ID0gdGVtcCkpICMgR2V0IG9iamVjdHMuDQogICAgICANCiAgICAgIGlmIChpcy5saXN0KHRlbXApICYmICJSZXN1bHQiICVpbiUgbmFtZXModGVtcCkpIHsNCiAgICAgICAgDQogICAgICAgIGlmIChpcy5kYXRhLmZyYW1lKHRlbXAkUmVzdWx0KSkNCiAgICAgICAgICBjb21tdW5pdHkgPC0gdGVtcCRSZXN1bHQkQ29tbXVuaXR5W1tucm93KHRlbXAkUmVzdWx0KV1dDQogICAgICAgIGVsc2UgDQogICAgICAgICAgY29tbXVuaXR5IDwtIHRlbXAkUmVzdWx0DQogICAgICAgIA0KICAgICAgICBzaXplIDwtIHRvU3RyaW5nKGxlbmd0aChjb21tdW5pdHkpKQ0KICAgICAgICANCiAgICAgICAgaWYgKGNvbW11bml0eVsxXSAhPSAiIikgDQogICAgICAgICAgYWJ1bmQgPC0gdG9TdHJpbmcodGVtcCRBYnVuZFtjb21tdW5pdHkgKyAxXSkNCiAgICAgICAgZWxzZSANCiAgICAgICAgICBhYnVuZCA8LSAiIg0KICAgICAgICANCiAgICAgICAgY29tbXVuaXR5IDwtIHRvU3RyaW5nKGNvbW11bml0eSkNCiAgICAgICAgDQogICAgICAgIGlmIChjb21tdW5pdHkgPT0gIiIpIHsNCiAgICAgICAgICByZXN1bHRzTGlzdCRgTm8gU3RhdGVgIDwtIHJlc3VsdHNMaXN0JGBObyBTdGF0ZWAgKyAxDQogICAgICAgICAgcmVzdWx0c1NpemUkYDBgIDwtIHJlc3VsdHNTaXplJGAwYCArIDENCiAgICAgICAgICANCiAgICAgICAgfSBlbHNlIGlmIChjb21tdW5pdHkgJWluJSBuYW1lcyhyZXN1bHRzTGlzdCkpIHsNCiAgICAgICAgICByZXN1bHRzTGlzdFtbY29tbXVuaXR5XV0gPC0gcmVzdWx0c0xpc3RbW2NvbW11bml0eV1dICsgMQ0KICAgICAgICAgIHJlc3VsdHNTaXplW1tzaXplXV0gPC0gcmVzdWx0c1NpemVbW3NpemVdXSArIDENCiAgICAgICAgICANCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICByZXN1bHRzTGlzdFtbY29tbXVuaXR5XV0gPC0gMQ0KICAgICAgICAgIHJlc3VsdHNBc3NlbWJseVtbY29tbXVuaXR5XV0gPC0gdGVtcA0KICAgICAgICAgIHJlc3VsdHNBYnVuZFtbY29tbXVuaXR5XV0gPC0gYWJ1bmQNCiAgICAgICAgICANCiAgICAgICAgICBpZiAoc2l6ZSAlaW4lIHJlc3VsdHNTaXplKSB7DQogICAgICAgICAgICByZXN1bHRzU2l6ZVtbc2l6ZV1dIDwtIHJlc3VsdHNTaXplW1tzaXplXV0gKyAxDQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIHJlc3VsdHNTaXplW1tzaXplXV0gPC0gMQ0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgcmVzdWx0c0xpc3QkYE5vIFN0YXRlYCA8LSByZXN1bHRzTGlzdCRgTm8gU3RhdGVgICsgMQ0KICAgICAgICByZXN1bHRzU2l6ZSRgMGAgPC0gcmVzdWx0c1NpemUkYDBgICsgMQ0KICAgICAgfQ0KICAgIH0gZWxzZSB7DQogICAgICByZXN1bHRzTGlzdCRgTm8gUnVuYCA8LSByZXN1bHRzTGlzdCRgTm8gUnVuYCArIDENCiAgICAgIHJlc3VsdHNTaXplJGAwYCA8LSByZXN1bHRzU2l6ZSRgMGAgKyAxDQogICAgfQ0KICB9DQogIA0KICBwYXJhbUZyYW1lJEVuZFN0YXRlc1tbaV1dIDwtIHJlc3VsdHNMaXN0DQogIHBhcmFtRnJhbWUkRW5kU3RhdGVzTnVtW2ldIDwtIGxlbmd0aChyZXN1bHRzTGlzdCkgLSAyICMgISBObyBTdGF0ZSwgTm8gUnVuDQogIHBhcmFtRnJhbWUkRW5kU3RhdGVTaXplc1tbaV1dIDwtIHJlc3VsdHNTaXplDQogIHBhcmFtRnJhbWUkRW5kU3RhdGVTaXplc051bVtpXSA8LSBsZW5ndGgocmVzdWx0c1NpemUpIC0gMSAjICEgMA0KICBwYXJhbUZyYW1lJEVuZFN0YXRlQXNzZW1ibHlbW2ldXSA8LSByZXN1bHRzQXNzZW1ibHkNCiAgcGFyYW1GcmFtZSRFbmRTdGF0ZUFidW5kYW5jZVtbaV1dIDwtIHJlc3VsdHNBYnVuZA0KfQ0KYGBgDQoNCmBgYHtyIG9yZ2FuaXNlUGFyYW1zMn0NCnNvdXJjZSgNCiAgZmlsZS5wYXRoKGdldHdkKCksIA0KICAgICAgICAgICAgIkxhd01vcnRvbjE5OTYtTnVtZXJpY2FsUG9vbENvbW11bml0eVNjYWxpbmctU2V0dGluZ3MxMC5SIikNCikNCg0Kb2xkTnJvdyA8LSBucm93KHBhcmFtRnJhbWUpDQoNCnBhcmFtRnJhbWUgPC0gcmJpbmQocGFyYW1GcmFtZSwgd2l0aChsaXN0KA0KICBiID0gcmVwKGJhc2FsLCB0aW1lcyA9IGxlbmd0aChjb25zdW1lcikpLA0KICBjID0gcmVwKGNvbnN1bWVyLCBlYWNoID0gbGVuZ3RoKGJhc2FsKSksDQogIHMxID0gc2VlZHNQcmVwWzE6KGxlbmd0aChiYXNhbCkgKiBsZW5ndGgoY29uc3VtZXIpKV0sDQogIHMyID0gc2VlZHNQcmVwWw0KICAgIChsZW5ndGgoYmFzYWwpICogbGVuZ3RoKGNvbnN1bWVyKSArIDEpOigNCiAgICAgIDIgKiBsZW5ndGgoYmFzYWwpICogbGVuZ3RoKGNvbnN1bWVyKSkNCiAgXSwNCiAgc1IgPSBzZWVkc1J1bg0KKSwgew0KICB0ZW1wIDwtIGRhdGEuZnJhbWUoDQogICAgQ29tYm5OdW0gPSAwLA0KICAgIEJhc2FscyA9IGIsDQogICAgQ29uc3VtZXJzID0gYywNCiAgICBTZWVkUG9vbCA9IHMxLA0KICAgIFNlZWRNYXQgPSBzMiwNCiAgICBTZWVkUnVucyA9ICIiLA0KICAgIFNlZWRSdW5zTnVtID0gMCwNCiAgICBFbmRTdGF0ZXMgPSBJKHJlcChsaXN0KCIiKSwgbGVuZ3RoKGIpKSksDQogICAgRW5kU3RhdGVzTnVtID0gMCwNCiAgICBFbmRTdGF0ZVNpemVzID0gSShyZXAobGlzdCgiIiksIGxlbmd0aChiKSkpLA0KICAgIEVuZFN0YXRlU2l6ZXNOdW0gPSBOQSwNCiAgICBFbmRTdGF0ZUFzc2VtYmx5ID0gSShyZXAobGlzdCgiIiksIGxlbmd0aChiKSkpLA0KICAgIEVuZFN0YXRlQWJ1bmRhbmNlID0gSShyZXAobGlzdCgiIiksIGxlbmd0aChiKSkpLA0KICAgIERhdGFzZXQgPSAiVmlraW5nMTAiLA0KICAgIERhdGFzZXRJRCA9IDIsDQogICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQogICkNCiAgZm9yIChpIGluIDE6bnJvdyh0ZW1wKSkgew0KICAgIHNlZWRzIDwtIHNSWygoaSAtIDEpICogcnVucyArIDEpIDogKGkgKiBydW5zKV0NCiAgICB0ZW1wJFNlZWRSdW5zW2ldIDwtIHRvU3RyaW5nKHNlZWRzKSAjIENTVg0KICAgIHRlbXAkU2VlZFJ1bnNOdW1baV0gPC0gbGVuZ3RoKHNlZWRzKQ0KICB9DQogIHRlbXAkQ29tYm5OdW0gPC0gMTpucm93KHRlbXApDQogIHRlbXANCn0pDQopDQpgYGANCg0KYGBge3IgbG9hZFJlc3VsdHMyfQ0KIyBOb3RlOiBuICsgMiBlbmQgc3RhdGVzLiBGYWlsdXJlIHRvIGZpbmlzaCwgZmFpbHVyZSB0byBvYnRhaW4gc3RhdGUsIGFuZCBzdGF0ZS4NCiMgTW9kaWZpZWQgZnJvbSBhYm92ZSwgYnV0IHdpdGggdGhlIGFidW5kYW5jZSByZWNvcmRlZC4NCmZvciAoaSBpbiAob2xkTnJvdyArIDEpOm5yb3cocGFyYW1GcmFtZSkpIHsNCiAgcmVzdWx0c0xpc3QgPC0gbGlzdCgNCiAgICAiTm8gUnVuIiA9IDAsDQogICAgIk5vIFN0YXRlIiA9IDANCiAgKQ0KICByZXN1bHRzU2l6ZSA8LSBsaXN0KA0KICAgICIwIiA9IDANCiAgKQ0KICByZXN1bHRzQXNzZW1ibHkgPC0gbGlzdCgNCiAgICAiTm8gUnVuIiA9IGRhdGEuZnJhbWUoKSwNCiAgICAiTm8gU3RhdGUiID0gZGF0YS5mcmFtZSgpDQogICkNCiAgcmVzdWx0c0FidW5kIDwtIGxpc3QoDQogICAgIk5vIFJ1biIgPSAiIiwNCiAgICAiTm8gU3RhdGUiID0gIiINCiAgKQ0KICBzZWVkcyA8LSB1bmxpc3Qoc3Ryc3BsaXQocGFyYW1GcmFtZSRTZWVkUnVuc1tpXSwgJywgJykpDQogIGZvciAoc2VlZCBpbiBzZWVkcykgew0KICAgIGZpbGVOYW1lIDwtIGZpbGUucGF0aCgNCiAgICAgIGRpclZpa2luZ1Jlc3VsdHNbcGFyYW1GcmFtZSREYXRhc2V0SURbaV1dLA0KICAgICAgc3ByaW50ZihyZXN1bHRGb3JtYXQsIHBhcmFtRnJhbWUkQ29tYm5OdW1baV0sIHNlZWQpDQogICAgKQ0KICAgIA0KICAgIGlmIChmaWxlLmV4aXN0cyhmaWxlTmFtZSkpIHsNCiAgICAgIHRlbXAgPC0gbG9hZChmaWxlTmFtZSkNCiAgICAgIHRlbXAgPC0gZXZhbChwYXJzZSh0ZXh0ID0gdGVtcCkpICMgR2V0IG9iamVjdHMuDQogICAgICANCiAgICAgIGlmIChpcy5saXN0KHRlbXApICYmICJSZXN1bHQiICVpbiUgbmFtZXModGVtcCkpIHsNCiAgICAgICAgDQogICAgICAgIGlmIChpcy5kYXRhLmZyYW1lKHRlbXAkUmVzdWx0KSkNCiAgICAgICAgICBjb21tdW5pdHkgPC0gdGVtcCRSZXN1bHQkQ29tbXVuaXR5W1tucm93KHRlbXAkUmVzdWx0KV1dDQogICAgICAgIGVsc2UgDQogICAgICAgICAgY29tbXVuaXR5IDwtIHRlbXAkUmVzdWx0DQogICAgICAgIA0KICAgICAgICBzaXplIDwtIHRvU3RyaW5nKGxlbmd0aChjb21tdW5pdHkpKQ0KICAgICAgICANCiAgICAgICAgaWYgKGNvbW11bml0eVsxXSAhPSAiIikgDQogICAgICAgICAgYWJ1bmQgPC0gdG9TdHJpbmcodGVtcCRBYnVuZFtjb21tdW5pdHkgKyAxXSkNCiAgICAgICAgZWxzZSANCiAgICAgICAgICBhYnVuZCA8LSAiIg0KICAgICAgICANCiAgICAgICAgY29tbXVuaXR5IDwtIHRvU3RyaW5nKGNvbW11bml0eSkNCiAgICAgICAgDQogICAgICAgIGlmIChjb21tdW5pdHkgPT0gIiIpIHsNCiAgICAgICAgICByZXN1bHRzTGlzdCRgTm8gU3RhdGVgIDwtIHJlc3VsdHNMaXN0JGBObyBTdGF0ZWAgKyAxDQogICAgICAgICAgcmVzdWx0c1NpemUkYDBgIDwtIHJlc3VsdHNTaXplJGAwYCArIDENCiAgICAgICAgICANCiAgICAgICAgfSBlbHNlIGlmIChjb21tdW5pdHkgJWluJSBuYW1lcyhyZXN1bHRzTGlzdCkpIHsNCiAgICAgICAgICByZXN1bHRzTGlzdFtbY29tbXVuaXR5XV0gPC0gcmVzdWx0c0xpc3RbW2NvbW11bml0eV1dICsgMQ0KICAgICAgICAgIHJlc3VsdHNTaXplW1tzaXplXV0gPC0gcmVzdWx0c1NpemVbW3NpemVdXSArIDENCiAgICAgICAgICANCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICByZXN1bHRzTGlzdFtbY29tbXVuaXR5XV0gPC0gMQ0KICAgICAgICAgIHJlc3VsdHNBc3NlbWJseVtbY29tbXVuaXR5XV0gPC0gdGVtcA0KICAgICAgICAgIHJlc3VsdHNBYnVuZFtbY29tbXVuaXR5XV0gPC0gYWJ1bmQNCiAgICAgICAgICANCiAgICAgICAgICBpZiAoc2l6ZSAlaW4lIHJlc3VsdHNTaXplKSB7DQogICAgICAgICAgICByZXN1bHRzU2l6ZVtbc2l6ZV1dIDwtIHJlc3VsdHNTaXplW1tzaXplXV0gKyAxDQogICAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgIHJlc3VsdHNTaXplW1tzaXplXV0gPC0gMQ0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgfSBlbHNlIHsNCiAgICAgICAgcmVzdWx0c0xpc3QkYE5vIFN0YXRlYCA8LSByZXN1bHRzTGlzdCRgTm8gU3RhdGVgICsgMQ0KICAgICAgICByZXN1bHRzU2l6ZSRgMGAgPC0gcmVzdWx0c1NpemUkYDBgICsgMQ0KICAgICAgfQ0KICAgIH0gZWxzZSB7DQogICAgICByZXN1bHRzTGlzdCRgTm8gUnVuYCA8LSByZXN1bHRzTGlzdCRgTm8gUnVuYCArIDENCiAgICAgIHJlc3VsdHNTaXplJGAwYCA8LSByZXN1bHRzU2l6ZSRgMGAgKyAxDQogICAgfQ0KICB9DQogIA0KICBwYXJhbUZyYW1lJEVuZFN0YXRlc1tbaV1dIDwtIHJlc3VsdHNMaXN0DQogIHBhcmFtRnJhbWUkRW5kU3RhdGVzTnVtW2ldIDwtIGxlbmd0aChyZXN1bHRzTGlzdCkgLSAyICMgISBObyBTdGF0ZSwgTm8gUnVuDQogIHBhcmFtRnJhbWUkRW5kU3RhdGVTaXplc1tbaV1dIDwtIHJlc3VsdHNTaXplDQogIHBhcmFtRnJhbWUkRW5kU3RhdGVTaXplc051bVtpXSA8LSBsZW5ndGgocmVzdWx0c1NpemUpIC0gMSAjICEgMA0KICBwYXJhbUZyYW1lJEVuZFN0YXRlQXNzZW1ibHlbW2ldXSA8LSByZXN1bHRzQXNzZW1ibHkNCiAgcGFyYW1GcmFtZSRFbmRTdGF0ZUFidW5kYW5jZVtbaV1dIDwtIHJlc3VsdHNBYnVuZA0KfQ0KYGBgDQoNCiMjIyBQbG90IFByZXBhcmF0aW9uDQoNCmBgYHtyIHBsb3QzRH0NCiMgWCwgWSwgQmFzYWwgYW5kIENvbnN1bWVyLg0KIyBaID0gU2l6ZXMgb2YgdGhlIEVuZHN0YXRlcy4NCg0KcGxvdFNjYWxpbmdEYXRhIDwtIGRhdGEuZnJhbWUoDQogIENvbWJuTnVtID0gcmVwKHBhcmFtRnJhbWUkQ29tYm5OdW0sIHBhcmFtRnJhbWUkRW5kU3RhdGVzTnVtKSwNCiAgQmFzYWxzID0gcmVwKHBhcmFtRnJhbWUkQmFzYWxzLCBwYXJhbUZyYW1lJEVuZFN0YXRlc051bSksDQogIENvbnN1bWVycyA9IHJlcChwYXJhbUZyYW1lJENvbnN1bWVycywgcGFyYW1GcmFtZSRFbmRTdGF0ZXNOdW0pLA0KICBEYXRhc2V0ID0gcmVwKHBhcmFtRnJhbWUkRGF0YXNldCwgcGFyYW1GcmFtZSRFbmRTdGF0ZXNOdW0pLA0KICBEYXRhc2V0SUQgPSByZXAocGFyYW1GcmFtZSREYXRhc2V0SUQsIHBhcmFtRnJhbWUkRW5kU3RhdGVzTnVtKQ0KKQ0KDQojIENvbW11bml0aWVzDQpjb21tcyA8LSB1bmxpc3QobGFwcGx5KHBhcmFtRnJhbWUkRW5kU3RhdGVzLCBuYW1lcykpDQpmcmVxcyA8LSB1bmxpc3QocGFyYW1GcmFtZSRFbmRTdGF0ZXMpDQphc21ibCA8LSB1bmxpc3QocGFyYW1GcmFtZSRFbmRTdGF0ZUFzc2VtYmx5LCByZWN1cnNpdmUgPSBGQUxTRSkNCmFzbWJsIDwtIGFzbWJsW2NvbW1zICE9ICJObyBSdW4iICYgY29tbXMgIT0gIk5vIFN0YXRlIl0NCmZyZXFzIDwtIGZyZXFzW2NvbW1zICE9ICJObyBSdW4iICYgY29tbXMgIT0gIk5vIFN0YXRlIl0NCmNvbW1zIDwtIGNvbW1zW2NvbW1zICE9ICJObyBSdW4iICYgY29tbXMgIT0gIk5vIFN0YXRlIl0NCg0KYXNtYmwgPC0gbGFwcGx5KGFzbWJsLCBmdW5jdGlvbihkKSB7DQogIGlmIChpcy5udWxsKGQpKSByZXR1cm4oTkEpDQogIGlmICgiUmVzdWx0Lk91dGNvbWUiICVpbiUgbmFtZXMoZCkpDQogICAgZCAlPiUgZHBseXI6OmZpbHRlcihSZXN1bHQuT3V0Y29tZSAhPSAiVHlwZSAxIChGYWlsdXJlKSIgJiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgUmVzdWx0Lk91dGNvbWUgIT0gIlByZXNlbnQiKQ0KICBlbHNlDQogICAgZCRSZXN1bHQgJT4lIGRwbHlyOjpmaWx0ZXIoT3V0Y29tZSAhPSAiVHlwZSAxIChGYWlsdXJlKSIgJiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE91dGNvbWUgIT0gIlByZXNlbnQiKQ0KfSkNCg0KcGxvdFNjYWxpbmdEYXRhJENvbW11bml0aWVzIDwtIGNvbW1zDQpwbG90U2NhbGluZ0RhdGEkQ29tbXVuaXR5RnJlcSA8LSBmcmVxcw0KcGxvdFNjYWxpbmdEYXRhJENvbW11bml0eVNlcSA8LSBhc21ibA0KDQojIENvbW11bml0eSBTaXplDQp0ZW1wIDwtIHVubGlzdChsYXBwbHkoc3Ryc3BsaXQocGxvdFNjYWxpbmdEYXRhJENvbW11bml0aWVzLCAnLCcpLCBsZW5ndGgpKQ0KcGxvdFNjYWxpbmdEYXRhJENvbW11bml0eVNpemUgPC0gdGVtcA0KDQpjYW5kaWRhdGVEYXRhIDwtIHBsb3RTY2FsaW5nRGF0YSAlPiUgZHBseXI6Omdyb3VwX2J5KA0KICBDb21ibk51bSwgRGF0YXNldA0KKSAlPiUgZHBseXI6Om11dGF0ZSgNCiAgT3RoZXJTdGVhZHlTdGF0ZXMgPSBkcGx5cjo6bigpIC0gMQ0KKQ0KYGBgDQoNCiMjIyBQb29scyBhbmQgTWF0cmljZXMNCmBgYHtyfQ0KbWF0cyA8LSBsaXN0KCkNCnBvb2xzYWxsIDwtIGxpc3QoKSAjIG5hbWUgcG9vbHMgdXNlZCBpbiBzYXZlIGRhdGE7IGJlIGNhcmVmdWwhDQoNCmZvciAoaSBpbiAxOmxlbmd0aChkaXJWaWtpbmcpKSB7DQogIHRlbXAgPC0gbG9hZChmaWxlLnBhdGgoDQogICAgZGlyVmlraW5nW2ldLCANCiAgICBwYXN0ZTAoIkxhd01vcnRvbjE5OTYtTnVtZXJpY2FsUG9vbENvbW11bml0eVNjYWxpbmctUG9vbE1hdHMiLCANCiAgICAgICAgICAgYyg5LCAxMClbaV0sIA0KICAgICAgICAgICAiLlJEUyIpDQogICkpDQogIG1hdHNbW2ldXSA8LSBldmFsKHBhcnNlKHRleHQgPSB0ZW1wWzFdKSkNCiAgcG9vbHNhbGxbW2ldXSA8LSBldmFsKHBhcnNlKHRleHQgPSB0ZW1wWzJdKSkNCn0NCnBvb2xzIDwtIHBvb2xzYWxsDQpgYGANCg0KIyMjIEFidW5kYW5jZXMNCmBgYHtyIGxvYWRBYnVuZGFuY2VzfQ0KIyBGaXJzdCwgY2hlY2sgaWYgaXQgaXMgaW4gdGhlIHBhcmFtRnJhbWUuDQojIFNlY29uZCwgY2hlY2sgaWYgaXQgaXMgaW4gdGhlIHNhdmVkIGRhdGEgZnJvbSB0aGUgcHJldmlvdXMuDQojIE90aGVyd2lzZSwgaWdub3JlIGl0LCB3ZSdsbCBmaWd1cmUgb3V0IHdoYXQgaXQgaXMgYW5kIHdoeSBpdCBpcyBtaXNzaW5nIGxhdGVyLg0KDQpjYW5kaWRhdGVEYXRhJENvbW11bml0eUFidW5kIDwtICIiDQoNCmZvciAociBpbiAxOm5yb3coY2FuZGlkYXRlRGF0YSkpIHsNCiAgIyBJRCAxOjQgYXJlIHVzZWQgdG8gaWRlbnRpZnkgcGFyYW1GcmFtZSwgNSB1c2VkIHRvIGlkZW50aWZ5IGFidW5kYW5jZQ0KICBJRCA8LSBjYW5kaWRhdGVEYXRhW3IsIDE6Nl0NCiAgcGFyYW1GcmFtZVJvdyA8LSBwYXJhbUZyYW1lICU+JSBkcGx5cjo6ZmlsdGVyKA0KICAgIENvbWJuTnVtID09IElEJENvbWJuTnVtLA0KICAgIEJhc2FscyA9PSBJRCRCYXNhbHMsDQogICAgQ29uc3VtZXJzID09IElEJENvbnN1bWVycywNCiAgICBEYXRhc2V0ID09IElEJERhdGFzZXQNCiAgKQ0KICANCiAgaWYgKGlzLmxpc3QocGFyYW1GcmFtZVJvdyRFbmRTdGF0ZUFidW5kYW5jZVtbMV1dKSkgew0KICAgIGVudHJ5IDwtIHdoaWNoKElEJENvbW11bml0aWVzID09IG5hbWVzKHBhcmFtRnJhbWVSb3ckRW5kU3RhdGVBYnVuZGFuY2VbWzFdXSkpDQogICAgaWYgKGxlbmd0aChlbnRyeSkpIHsNCiAgICAgIGNhbmRpZGF0ZURhdGEkQ29tbXVuaXR5QWJ1bmRbcl0gPC0gcGFyYW1GcmFtZVJvdyRFbmRTdGF0ZUFidW5kYW5jZVtbMV1dW1tlbnRyeV1dDQogICAgICBuZXh0KCkNCiAgICB9DQogIH0NCn0NCmBgYA0KDQpgYGB7ciBmaWx0ZXJOb0FidW5kfQ0KcHJpbnQocGFzdGUoIkZhaWx1cmVzOiIsIA0KICAgICAgICAgICAgc3VtKGNhbmRpZGF0ZURhdGEkQ29tbXVuaXR5QWJ1bmQgJWluJSANCiAgICAgICAgICAgICAgICAgIGMoIiIsICJGYWlsdXJlIiwgIkVzdGltYXRlZEZhaWx1cmUiKSkpKQ0KY2FuZGlkYXRlRGF0YSA8LSBjYW5kaWRhdGVEYXRhICU+JSBkcGx5cjo6ZmlsdGVyKENvbW11bml0eUFidW5kICE9ICIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENvbW11bml0eUFidW5kICE9ICJGYWlsdXJlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb21tdW5pdHlBYnVuZCAhPSAiRXN0aW1hdGVGYWlsdXJlIikNCmBgYA0KDQpgYGB7ciBjb21wdXRlUHJvZHVjdGl2aXR5fQ0KY2FuZGlkYXRlRGF0YSRDb21tdW5pdHlQcm9kIDwtIE5BDQpmb3IgKHIgaW4gMTpucm93KGNhbmRpZGF0ZURhdGEpKSB7DQogIGNhbmRpZGF0ZURhdGEkQ29tbXVuaXR5UHJvZFtyXSA8LSB3aXRoKA0KICAgIGNhbmRpZGF0ZURhdGFbciwgXSwgDQogICAgUk1UUkNvZGUyOjpQcm9kdWN0aXZpdHkoDQogICAgICBQb29sID0gcG9vbHNbW0RhdGFzZXRJRF1dW1tDb21ibk51bV1dLCANCiAgICAgIEludGVyYWN0aW9uTWF0cml4ID0gbWF0c1tbRGF0YXNldElEXV1bW0NvbWJuTnVtXV0sIA0KICAgICAgQ29tbXVuaXR5ID0gQ29tbXVuaXRpZXMsIA0KICAgICAgUG9wdWxhdGlvbnMgPSBDb21tdW5pdHlBYnVuZA0KICAgICkNCiAgKQ0KfQ0KYGBgDQoNCmBgYHtyIGZpbHRlck51bWVyaWNhbGx5VW5zdGFibGV9DQpwcmludChwYXN0ZSgiTnVtZXJpY2FsbHkgVW5zdGFibGU6IiwgDQogICAgICAgICAgICBzdW0oY2FuZGlkYXRlRGF0YSRDb21tdW5pdHlQcm9kID4gMTBeMTAgDQogICAgICAgICAgICAgICAgICApKSkNCmNhbmRpZGF0ZURhdGEgPC0gY2FuZGlkYXRlRGF0YSAlPiUgZHBseXI6OmZpbHRlcihDb21tdW5pdHlQcm9kIDwgMTBeMTApDQpgYGANCg0KIyMgQ29tbXVuaXRpZXMNCmBgYHtyIHdoYXRyZW1haW5zLCBvdXQud2lkdGg9IjEwMCUifQ0KIyBGb3IgdXNhZ2UgYnkgdGhlIHJlYWRlci4NCg0KcGxvdFNjYWxpbmcgPC0gcGxvdGx5OjpwbG90X2x5KA0KICBjYW5kaWRhdGVEYXRhLA0KICB4ID0gfkJhc2FscywNCiAgeSA9IH5Db25zdW1lcnMsDQogIHogPSB+Q29tbXVuaXR5U2l6ZSwNCiAgY29sb3IgPSB+RGF0YXNldCwNCiAgY29sb3JzID0gYygicmVkIiwgImJsdWUiLCAiYmxhY2siKQ0KKQ0KDQpwbG90U2NhbGluZyA8LSBwbG90bHk6OmFkZF9tYXJrZXJzKHBsb3RTY2FsaW5nKQ0KDQpwbG90U2NhbGluZyA8LSBwbG90bHk6OmxheW91dCgNCiAgcGxvdFNjYWxpbmcsDQogIHNjZW5lID0gbGlzdCgNCiAgICB4YXhpcyA9IGxpc3QodHlwZSA9ICJsb2ciKSwNCiAgICB5YXhpcyA9IGxpc3QodHlwZSA9ICJsb2ciKSwNCiAgICBjYW1lcmEgPSBsaXN0KA0KICAgICAgZXllID0gbGlzdCgNCiAgICAgICAgeCA9IC0xLjI1LCB5ID0gLTEuMjUsIHogPSAuMDUNCiAgICAgICkNCiAgICApDQogICkNCikNCg0KcGxvdFNjYWxpbmcNCmBgYA0KDQojIyBDb21tdW5pdGllcyBEYXRhDQpgYGB7cn0NCmNhbmRpZGF0ZURhdGENCmBgYA0KDQojIyBGb29kd2VicywgUHJlcA0KYGBge3IgY3JlYXRlR3JhcGhzfQ0KZm9vZFdlYnMgPC0gbGlzdCgpDQoNCmZvciAociBpbiAxOm5yb3coY2FuZGlkYXRlRGF0YSkpIHsNCiAgZm9vZFdlYnNbW3JdXSA8LSB3aXRoKA0KICAgIGNhbmRpZGF0ZURhdGFbciwgXSwNCiAgICB7DQogICAgICByZWRDb20gPC0gUk1UUkNvZGUyOjpDc3ZSb3dTcGxpdChDb21tdW5pdGllcykNCiAgICAgIHJlZE1hdCA8LSBtYXRzW1tEYXRhc2V0SURdXVtbQ29tYm5OdW1dXVtyZWRDb20sIHJlZENvbV0NCiAgICAgIHJlZFBvb2wgPC0gcG9vbHNbW0RhdGFzZXRJRF1dW1tDb21ibk51bV1dW3JlZENvbSwgXQ0KICAgICAgDQogICAgICBjb2xuYW1lcyhyZWRNYXQpIDwtIHBhc3RlMCgncycsYXMuY2hhcmFjdGVyKHJlZENvbSkpDQogICAgICByb3duYW1lcyhyZWRNYXQpIDwtIGNvbG5hbWVzKHJlZE1hdCkNCiAgICAgIA0KICAgICAgbmFtZXMocmVkUG9vbClbMV0gPC0gIm5vZGUiDQogICAgICByZWRQb29sJG5vZGUgPC0gY29sbmFtZXMocmVkTWF0KQ0KICAgICAgbmFtZXMocmVkUG9vbClbM10gPC0gIk0iDQogICAgICANCiAgICAgIEdyYXBoIDwtIGlncmFwaDo6Z3JhcGhfZnJvbV9hZGphY2VuY3lfbWF0cml4KA0KICAgICAgICByZWRNYXQsIHdlaWdodGVkID0gVFJVRQ0KICAgICAgKQ0KICAgICAgDQogICAgICBHcmFwaCA8LSBpZ3JhcGg6OnNldC52ZXJ0ZXguYXR0cmlidXRlKA0KICAgICAgICBHcmFwaCwgIm5hbWUiLCB2YWx1ZSA9IGNvbG5hbWVzKHJlZE1hdCkNCiAgICAgICkNCiAgICAgIA0KICAgICAgcmVkUG9vbCROIDwtIFJNVFJDb2RlMjo6Q3N2Um93U3BsaXQoQ29tbXVuaXR5QWJ1bmQpDQogICAgICANCiAgICAgICMgRm9yIGxhdGVyIGFuYWx5c2lzLCB0YWtlIHRoZSBtYXRyaXggZGlhZ29uYWwuDQogICAgICANCiAgICAgIHJlZFBvb2wkSW50cmFzcGVjaWZpYyA8LSBkaWFnKHJlZE1hdCkNCiAgICAgIA0KICAgICAgR3JhcGhBc0RhdGFGcmFtZSA8LSBpZ3JhcGg6OmFzX2RhdGFfZnJhbWUoR3JhcGgpDQogIA0KICAgICAgIyBBZGQgaW4gYWJ1bmRhbmNlcyBmb3IgY2FsY3VsYXRpbmcgYWJ1bmRhbmNlICogKGdhaW4gb3IgbG9zcykNCiAgICAgIEdyYXBoQXNEYXRhRnJhbWUgPC0gZHBseXI6OmxlZnRfam9pbigNCiAgICAgICAgR3JhcGhBc0RhdGFGcmFtZSwNCiAgICAgICAgZHBseXI6OnNlbGVjdChyZWRQb29sLCBub2RlLCBOKSwNCiAgICAgICAgYnkgPSBjKCJ0byIgPSAibm9kZSIpDQogICAgICApDQogIA0KICAgICAgIyBTcGxpdCBkYXRhIGZyYW1lLg0KICAgICAgUmVzQ29uIDwtIEdyYXBoQXNEYXRhRnJhbWVbR3JhcGhBc0RhdGFGcmFtZSR3ZWlnaHQgPiAwLF0NCiAgICAgIENvblJlcyA8LSBHcmFwaEFzRGF0YUZyYW1lW0dyYXBoQXNEYXRhRnJhbWUkd2VpZ2h0IDwgMCxdDQogICAgICANCiAgICAgICMgUmVvcmRlciBhbmQgcmVuYW1lIHZhcmlhYmxlcy4NCiAgICAgIFJlc0NvbiA8LSBkcGx5cjo6c2VsZWN0KFJlc0NvbiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bywgZnJvbSwgIyByZXNvdXJjZSA9IHRvLCBjb25zdW1lciA9IGZyb20sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWZmZWN0UGVyVW5pdCA9IHdlaWdodCwgcmVzb3VyY2VBYnVuZCA9IE4pDQogICAgICBDb25SZXMgPC0gZHBseXI6OnNlbGVjdChDb25SZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG8sIGZyb20sICMgcmVzb3VyY2UgPSBmcm9tLCBjb25zdW1lciA9IHRvLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVmZmVjdFBlclVuaXQgPSB3ZWlnaHQsIGNvbnN1bWVyQWJ1bmQgPSBOKQ0KICAgICAgUmVzQ29uIDwtIGRwbHlyOjptdXRhdGUoZHBseXI6Omdyb3VwX2J5KFJlc0NvbiwgZnJvbSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZmZlY3RBY3R1YWwgPSBlZmZlY3RQZXJVbml0ICogcmVzb3VyY2VBYnVuZCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFR5cGUgPSAiRXhwbG9pdCsiKQ0KICAgICAgQ29uUmVzIDwtIGRwbHlyOjptdXRhdGUoZHBseXI6Omdyb3VwX2J5KENvblJlcywgZnJvbSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZmZlY3RBY3R1YWwgPSBlZmZlY3RQZXJVbml0ICogY29uc3VtZXJBYnVuZCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFR5cGUgPSBpZmVsc2UoZnJvbSA9PSB0bywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNlbGZSZWctIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkV4cGxvaXQtIikpDQogICAgICANCiAgICAgIEludHJpRyA8LSB3aXRoKHJlZFBvb2wsIGRhdGEuZnJhbWUoDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tID0gbm9kZSwgI3Jlc291cmNlID0gbm9kZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvID0gbm9kZSwgI2NvbnN1bWVyID0gbm9kZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVmZmVjdFBlclVuaXQgPSBpZmVsc2UoUmVwcm9kdWN0aW9uUmF0ZSA+IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZXByb2R1Y3Rpb25SYXRlLCAwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVmZmVjdEFjdHVhbCA9IGlmZWxzZShSZXByb2R1Y3Rpb25SYXRlID4gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTiAqIFJlcHJvZHVjdGlvblJhdGUsIDApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHlwZSA9ICJJbnRyaXNjKyIpKSANCiAgICAgIEludHJpTCA8LSB3aXRoKHJlZFBvb2wsIGRhdGEuZnJhbWUoDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tID0gbm9kZSwgI3Jlc291cmNlID0gbm9kZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvID0gbm9kZSwgI2NvbnN1bWVyID0gbm9kZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVmZmVjdFBlclVuaXQgPSBpZmVsc2UoUmVwcm9kdWN0aW9uUmF0ZSA8IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZXByb2R1Y3Rpb25SYXRlLCAwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVmZmVjdEFjdHVhbCA9IGlmZWxzZShSZXByb2R1Y3Rpb25SYXRlIDwgMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTiAqIFJlcHJvZHVjdGlvblJhdGUsIDApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHlwZSA9ICJJbnRyaXNjLSIpKQ0KICAgICAgDQogICAgICBFZGdlRGF0YUZyYW1lIDwtIGRwbHlyOjpiaW5kX3Jvd3MoDQogICAgICAgIGRwbHlyOjpzZWxlY3QoUmVzQ29uLCAtcmVzb3VyY2VBYnVuZCksIA0KICAgICAgICBkcGx5cjo6c2VsZWN0KENvblJlcywgLWNvbnN1bWVyQWJ1bmQpLA0KICAgICAgICBJbnRyaUcsIEludHJpTA0KICAgICAgKQ0KICAgICAgDQogICAgICBFZGdlRGF0YUZyYW1lIDwtIEVkZ2VEYXRhRnJhbWUgJT4lIGRwbHlyOjpyZW5hbWUoDQogICAgICAgICMgRW1waXJpY2FsbHkgc3BlYWtpbmcsIHRvIGFuZCBmcm9tIGFwcGVhciByZXZlcnNlZC4NCiAgICAgICAgIyBBIGNvbnN1bWVyIChmcm9tKSBzaG91bGQgaGF2ZSBhIG5lZ2F0aXZlIGVmZmVjdCBvbiByZXNvdXJjZSAodG8pLA0KICAgICAgICAjIGJ1dCB0aGUgb3JnYW5pc2F0aW9uIHNvIGZhciBtYXJrcyBpdCBhcyBwb3NpdGl2ZS4gV2UgZml4IHRoaXMuDQogICAgICAgIHRlbXBuYW1lID0gdG8sDQogICAgICAgIHRvID0gZnJvbQ0KICAgICAgKSAlPiUgZHBseXI6OnJlbmFtZSgNCiAgICAgICAgZnJvbSA9IHRlbXBuYW1lDQogICAgICApICU+JSBkcGx5cjo6ZmlsdGVyKA0KICAgICAgICAjIFJlbW92ZSBwbGFjZWhvbGRlciBlbnRyaWVzDQogICAgICAgIGVmZmVjdFBlclVuaXQgIT0gMA0KICAgICAgKSAlPiUgZHBseXI6Om11dGF0ZSgNCiAgICAgICAgIyBVc2VmdWwgdG8ga2VlcCBlZmZlY3RzIHNlcGFyYXRlDQogICAgICAgIGVmZmVjdFNpZ24gPSBzaWduKGVmZmVjdFBlclVuaXQpDQogICAgICApICU+JSBncm91cF9ieSgNCiAgICAgICAgdG8sIGVmZmVjdFNpZ24NCiAgICAgICkgJT4lIGRwbHlyOjptdXRhdGUoDQogICAgICAgICMgUGVyZm9ybSB0aGUgcG9zdCBtb3J0ZW0gb2YgdGhlIG1vc3QgaW5mbHVlbnRpYWwgZnJvbSdzDQogICAgICAgIGVmZmVjdEVmZmljaWVuY3kgPSBlZmZlY3RQZXJVbml0IC8gc3VtKGVmZmVjdFBlclVuaXQpLCANCiAgICAgICAgZWZmZWN0Tm9ybWFsaXNlZCA9IGVmZmVjdEFjdHVhbCAvIHN1bShlZmZlY3RBY3R1YWwpDQogICAgICApICU+JSBkcGx5cjo6YXJyYW5nZSh0bykNCiAgICAgIA0KICAgICAgbGlzdCgNCiAgICAgICAgRWRnZXMgPSBFZGdlRGF0YUZyYW1lLA0KICAgICAgICBWZXJ0aWNlcyA9IHJlZFBvb2wNCiAgICAgICkNCiAgICB9DQogICkNCn0NCmBgYA0KDQpgYGB7ciBmdW5jdGlvbnN9DQp0b0NoZWRkYXIgPC0gZnVuY3Rpb24oRVZMaXN0LCBuYW1lID0gIiIpIHsjIEVkZ2VzIFZlcnRpY2VzIExpc3QNCiAgbGlua3MgPC0gRVZMaXN0JEVkZ2VzDQoNCiAgIyBjaGVkZGFyIGRvZXMgbm90IGxpa2UgImNhbm5pYmFsaXNtIi4NCiAgbGlua3MgPC0gbGlua3NbDQogICAgbGlua3MkdG8gIT0gbGlua3MkZnJvbSwNCiAgXQ0KDQogICMgIltDXW9sdW1ucyBjYWxsZWQg4oCYcmVzb3VyY2XigJkgYW5kIOKAmGNvbnN1bWVy4oCZIG11c3QgYmUgZ2l2ZW4uIg0KICBsaW5rcyA8LSBkcGx5cjo6YmluZF9yb3dzKA0KICAgIGxpbmtzICU+JSBkcGx5cjo6ZmlsdGVyKGVmZmVjdFNpZ24gPT0gMSkgJT4lIGRwbHlyOjpyZW5hbWUoDQogICAgICByZXNvdXJjZSA9IGZyb20sIGNvbnN1bWVyID0gdG8pLA0KICAgIGxpbmtzICU+JSBkcGx5cjo6ZmlsdGVyKGVmZmVjdFNpZ24gPT0gLTEpICU+JSBkcGx5cjo6cmVuYW1lKA0KICAgICAgcmVzb3VyY2UgPSB0bywgY29uc3VtZXIgPSBmcm9tKSwNCiAgKSAlPiUgZHBseXI6OnNlbGVjdCgtVHlwZSkgIyBDaGVkZGFyIGNvbmZ1c2VzIG5vZGUgVHlwZSBhbmQgZWRnZSBUeXBlLg0KDQogIGNoZWRkYXI6OkNvbW11bml0eSgNCiAgICBub2RlcyA9IEVWTGlzdCRWZXJ0aWNlcywNCiAgICBwcm9wZXJ0aWVzID0gbGlzdCgNCiAgICAgIHRpdGxlID0gbmFtZSwNCiAgICAgIE0udW5pdHMgPSAibWFzc2VzIiwNCiAgICAgIE4udW5pdHMgPSAiYWJ1bmQiDQogICAgKSwNCiAgICB0cm9waGljLmxpbmtzID0gbGlua3MNCiAgKQ0KfQ0KDQp0b0lHcmFwaCA8LSBmdW5jdGlvbihFVkxpc3QsIHNpZ24gPSAwKSB7DQogIGlncmFwaDo6Z3JhcGhfZnJvbV9kYXRhX2ZyYW1lKA0KICAgIGQgPSBpZihzaWduID09IDApIHsNCiAgICAgIEVWTGlzdCRFZGdlcw0KICAgIH0gZWxzZSB7DQogICAgICBFVkxpc3QkRWRnZXNbRVZMaXN0JEVkZ2VzJGVmZmVjdFNpZ24gPT0gc2lnbiwgXQ0KICAgIH0sDQogICAgZGlyZWN0ZWQgPSBUUlVFLA0KICAgIHZlcnRpY2VzID0gRVZMaXN0JFZlcnRpY2VzDQogICkNCn0NCg0KDQp0b1Bvc3RNb3J0ZW0gPC0gZnVuY3Rpb24oRVZMaXN0LA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRocmVzaG9sZCA9IDAsICMgc2V0cyB0byBtaW5pbWFsIHNpemUgZWRnZXMgYmVsb3cNCiAgICAgICAgICAgICAgICAgICAgICAgICBub2RlU2l6ZSA9IGMoIk5vbmUiLCAiQWJ1bmRhbmNlIiwgIlNpemUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBlZGdlU2NhbGUgPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y2VkVHJvcGhpYyA9IFRSVUUpIHsNCiAgaWYgKHRvbG93ZXIodGhyZXNob2xkKSA9PSAiYWRhcHRpdmUiKSB7DQogICAgdGhyZXNob2xkID0gRVZMaXN0JEVkZ2VzICU+JSBncm91cF9ieSgNCiAgICAgIHRvLCBlZmZlY3RTaWduDQogICAgKSAlPiUgc3VtbWFyaXNlKA0KICAgICAgbWF4ID0gbWF4KGVmZmVjdE5vcm1hbGlzZWQpLCAuZ3JvdXBzID0gImRyb3AiDQogICAgKSAlPiUgdW5ncm91cCAlPiUgcHVsbChtYXgpICU+JSBtaW4NCiAgfQ0KDQogIHRoZUdjIDwtIHRvQ2hlZGRhcihFVkxpc3QsIG5hbWUgPSAiVHJvcGhpYyBMZXZlbHMiKQ0KICB0aGVHaSA8LSB0b0lHcmFwaChFVkxpc3QpDQoNCiAgdGhlR2lHYWluIDwtIHRvSUdyYXBoKEVWTGlzdCwgc2lnbiA9IDEpDQogIHRoZUdpTG9zcyA8LSB0b0lHcmFwaChFVkxpc3QsIHNpZ24gPSAtMSkNCg0KICB0aGVMYXlvdXQgPC0gaWdyYXBoOjpsYXlvdXQuY2lyY2xlKHRoZUdpKQ0KDQogIHRoZVNpemUgPC0gbWF0Y2guYXJnKG5vZGVTaXplLCBjKCJBYnVuZGFuY2UiLCAiU2l6ZSIsICJOb25lIikpDQogIGlmICh0aGVTaXplID09ICJBYnVuZGFuY2UiKQ0KICAgIHRoZVZzIDwtIHNxcnQoaWdyYXBoOjp2ZXJ0ZXhfYXR0cih0aGVHaSkkTikgKiAxMA0KICBlbHNlIGlmICh0aGVTaXplID09ICJTaXplIikgew0KICAgIHRoZVZzIDwtIGlncmFwaDo6dmVydGV4X2F0dHIodGhlR2kpJE0NCiAgICB0aGVWcyA8LSBzcXJ0KHRoZVZzIC8gbWluKHRoZVZzKSkgKiAxMA0KICB9IGVsc2UgaWYgKHRoZVNpemUgPT0gIk5vbmUiKSB7DQogICAgdGhlVnMgPC0gMTUNCiAgfQ0KDQogIHRoZUNvbG9ycyA8LSBpZmVsc2UoDQogICAgaWdyYXBoOjp2ZXJ0ZXhfYXR0cih0aGVHaSkkVHlwZSA9PSAiQmFzYWwiLCAic2t5Ymx1ZSIsICJyZWQiDQogICkNCiAgaWYgKCJDb3JlIiAlaW4lIG5hbWVzKGlncmFwaDo6dmVydGV4X2F0dHIodGhlR2kpKSkgew0KICAgIHRoZVNoYXBlcyA8LSBpZmVsc2UoaWdyYXBoOjp2ZXJ0ZXhfYXR0cih0aGVHaSkkQ29yZSwNCiAgICAgICAgICAgICAgICAgICAgICAgIDAsDQogICAgICAgICAgICAgICAgICAgICAgICAxKQ0KICB9IGVsc2Ugew0KICAgIHRoZVNoYXBlcyA8LSAxIA0KICAgICMgTm90ZSBJZ3JhcGggdXNlcyAiY2lyY2xlIiB0aGVuICJyZWN0YW5nbGUiLA0KICAgICMgYnV0IFIgYW5kIGNoZWRkYXIgdXNlICJyZWN0YW5nbGUiIHRoZW4gImNpcmNsZSIsIHNvIHdlIHdpbGwgdXNlIGEgIS4NCiAgfQ0KDQogIHRoZUJvdGggPC0gaWdyYXBoOjplZGdlX2F0dHIodGhlR2kpJGVmZmVjdE5vcm1hbGlzZWQNCiAgdGhlR2FpbiA8LSBpZ3JhcGg6OmVkZ2VfYXR0cih0aGVHaUdhaW4pJGVmZmVjdE5vcm1hbGlzZWQNCiAgdGhlTG9zcyA8LSBpZ3JhcGg6OmVkZ2VfYXR0cih0aGVHaUxvc3MpJGVmZmVjdE5vcm1hbGlzZWQNCg0KICB0aGVCb3RoW3RoZUJvdGggPCB0aHJlc2hvbGRdIDwtIDANCiAgdGhlR2Fpblt0aGVHYWluIDwgdGhyZXNob2xkXSA8LSAwDQogIHRoZUxvc3NbdGhlTG9zcyA8IHRocmVzaG9sZF0gPC0gMA0KDQogICMgSW5mb3JtIHRoZSBncmFwaHMgb2Ygd2hpY2ggZWRnZXMgYXJlIG5vdCBuZWVkZWQuDQogIHRoZUdpIDwtIGlncmFwaDo6ZGVsZXRlX2VkZ2VzKHRoZUdpLCB3aGljaCh0aGVCb3RoID09IDApKQ0KICB0aGVHaUdhaW4gPC0gaWdyYXBoOjpkZWxldGVfZWRnZXModGhlR2lHYWluLCB3aGljaCh0aGVHYWluID09IDApKQ0KICB0aGVHaUxvc3MgPC0gaWdyYXBoOjpkZWxldGVfZWRnZXModGhlR2lMb3NzLCB3aGljaCh0aGVMb3NzID09IDApKQ0KDQogICMgUmVtb3ZlIHRoZSBzYW1lIGVudHJpZXMgc28gdGhhdCBsZW5ndGhzIG1hdGNoLg0KICB0aGVHYWluIDwtIHRoZUdhaW5bdGhlR2FpbiA+IDBdDQogIHRoZUxvc3MgPC0gdGhlTG9zc1t0aGVMb3NzID4gMF0NCg0KICB0aGVHYWluIDwtIHRoZUdhaW4gKiBlZGdlU2NhbGUNCiAgdGhlTG9zcyA8LSB0aGVMb3NzICogZWRnZVNjYWxlDQoNCiAgcGFyb2xkIDwtIHBhcihuby5yZWFkb25seSA9IFRSVUUpDQogIHBhcihtZnJvdyA9IGMoMiwgMiksICMgVHdvIFJvd3MsIFR3byBDb2x1bW5zDQogICAgICBtYXIgPSBjKDAsIDEuNSwgMSwgMCksICMgTWFyZ2lucywgYm90dG9tLCBsZWZ0LCB0b3AsIHJpZ2h0DQogICAgICBvbWEgPSBjKDAuMSwgMC4xLCAwLjEsIDAuMSkgIyBPdXRlciBtYXJnaW5zLg0KICApDQoNCiAgY2hlZGRhcjo6UGxvdFdlYkJ5TGV2ZWwoDQogICAgdGhlR2MsDQogICAgc2hvdy5sZXZlbC5saW5lcyA9IFRSVUUsDQogICAgIyBIYWQgYmVlbiB1c2luZyBMb25nV2VpZ2h0ZWQsIGJ1dCB0aGF0IHNlZW1zIHRvIGdpdmUgdGhlIHVwc2lkZSBkb3duIFQuDQogICAgIyBGbG93IGJhc2VkIHNlZW1zIHRvIGJlIG1vcmUgd2hhdCB3ZSBhcmUgZXhwZWN0aW5nLCBnaXZlbiB0aGUgdXNhZ2Ugb2YNCiAgICAjIHRocmVzaG9sZGluZyBhbmQgd2hhdCB0aGF0IHNob3dzLiBUaGUgZmxvd3MgaGVyZSBhcmUgZXhwZWN0ZWQgdG8gYmUNCiAgICAjIGZsb3dzIG9mIGVuZXJneSB0aHJvdWdoIHRoZSBmb29kIHdlYi4NCiAgICBsZXZlbCA9IGNoZWRkYXI6OkZsb3dCYXNlZFRyb3BoaWNMZXZlbCh0aGVHYywgd2VpZ2h0LmJ5ID0gImVmZmVjdE5vcm1hbGlzZWQiKSwNCiAgICAgIGNvbCA9IHRoZUNvbG9ycywNCiAgICAgIHBjaCA9IHRoZVNoYXBlcw0KICApDQoNCiAgaWYgKCFyZWR1Y2VkVHJvcGhpYykgew0KICAgIHBsb3QoDQogICAgICB0aGVHaSwNCiAgICAgIGxheW91dCA9IHRoZUxheW91dCwNCiAgICAgIHZlcnRleC5zaXplID0gdGhlVnMsDQogICAgICBlZGdlLndpZHRoID0gMSwNCiAgICAgIGVkZ2UuYXJyb3cuc2l6ZSA9IDAuMywNCiAgICAgIGVkZ2UuYXJyb3cud2lkdGggPSAxLA0KICAgICAgdmVydGV4LmNvbG9yID0gdGhlQ29sb3JzLA0KICAgICAgdmVydGV4LnNoYXBlID0gaWdyYXBoOjpzaGFwZXMoKVthcy5udW1lcmljKCF0aGVTaGFwZXMpICsgMV0sDQogICAgICBlZGdlLmx0eSA9IDIsDQogICAgICBlZGdlLmNvbG9yID0gImdyZXkiLA0KICAgICAgZWRnZS5hcnJvdy5tb2RlID0gIj4iLA0KICAgICAgbWFpbiA9ICJDb25zdW1wdGlvbiINCiAgICApDQogIH0gZWxzZSB7DQogICAgRVZMaXN0UmVkIDwtIEVWTGlzdA0KICAgIEVWTGlzdFJlZCRFZGdlcyA8LSBFVkxpc3RSZWQkRWRnZXMgJT4lIGRwbHlyOjpmaWx0ZXIoDQogICAgICBlZmZlY3ROb3JtYWxpc2VkID49IHRocmVzaG9sZA0KICAgICkNCiAgICB0aGVHYzIgPC0gdG9DaGVkZGFyKEVWTGlzdFJlZCwgbmFtZSA9ICJTdHJvbmdlc3QgVHJvcGhpYyBMZXZlbHMiKQ0KICAgIGNoZWRkYXI6OlBsb3RXZWJCeUxldmVsKA0KICAgICAgdGhlR2MyLA0KICAgICAgc2hvdy5sZXZlbC5saW5lcyA9IFRSVUUsDQogICAgbGV2ZWwgPSBjaGVkZGFyOjpGbG93QmFzZWRUcm9waGljTGV2ZWwodGhlR2MyLCB3ZWlnaHQuYnkgPSAiZWZmZWN0Tm9ybWFsaXNlZCIpLA0KICAgICAgY29sID0gdGhlQ29sb3JzLA0KICAgICAgcGNoID0gdGhlU2hhcGVzDQogICAgKQ0KICB9DQoNCiAgcGxvdCgNCiAgICB0aGVHaUdhaW4sDQogICAgbGF5b3V0ID0gdGhlTGF5b3V0LA0KICAgIHZlcnRleC5zaXplID0gdGhlVnMsDQogICAgZWRnZS53aWR0aCA9IHRoZUdhaW4sDQogICAgZWRnZS5hcnJvdy5zaXplID0gMC4zLA0KICAgIGVkZ2UuYXJyb3cud2lkdGggPSAxLA0KICAgIHZlcnRleC5jb2xvciA9IHRoZUNvbG9ycywNCiAgICAgIHZlcnRleC5zaGFwZSA9IGlncmFwaDo6c2hhcGVzKClbYXMubnVtZXJpYyghdGhlU2hhcGVzKSArIDFdLA0KICAgIGVkZ2UubHR5ID0gMiwNCiAgICBlZGdlLmNvbG9yID0gImJsdWUiLA0KICAgIGVkZ2UuYXJyb3cubW9kZSA9ICI+IiwNCiAgICBtYWluID0gIkNvbnN1bWVyJ3MgR2FpbnMiDQogICkNCg0KICBwbG90KA0KICAgIHRoZUdpTG9zcywNCiAgICBsYXlvdXQgPSB0aGVMYXlvdXQsDQogICAgdmVydGV4LnNpemUgPSB0aGVWcywNCiAgICBlZGdlLndpZHRoID0gdGhlTG9zcywNCiAgICBlZGdlLmFycm93LnNpemUgPSAwLjMsDQogICAgZWRnZS5hcnJvdy53aWR0aCA9IDIsDQogICAgdmVydGV4LmNvbG9yID0gdGhlQ29sb3JzLA0KICAgICAgdmVydGV4LnNoYXBlID0gaWdyYXBoOjpzaGFwZXMoKVthcy5udW1lcmljKCF0aGVTaGFwZXMpICsgMV0sDQogICAgZWRnZS5sdHkgPSAzLA0KICAgIGVkZ2UuY29sb3IgPSAiZGFya3JlZCIsDQogICAgZWRnZS5hcnJvdy5tb2RlID0gIjwiLA0KICAgIG1haW4gPSAiUmVzb3VyY2UncyBMb3NzZXMiDQogICkNCiAgDQogIHBhcihwYXJvbGQpDQogIA0KICBFVkxpc3QkRWRnZXMgJT4lIGRwbHlyOjp1bmdyb3VwKCkgJT4lIGRwbHlyOjpmaWx0ZXIoDQogICAgZWZmZWN0Tm9ybWFsaXNlZCA+PSB0aHJlc2hvbGQNCiAgKSAlPiUgZHBseXI6OnNlbGVjdCgNCiAgICAtZWZmZWN0U2lnbg0KICApICU+JSBkcGx5cjo6YXJyYW5nZSgNCiAgICB0bywgLWVmZmVjdE5vcm1hbGlzZWQNCiAgKQ0KfQ0KDQpgYGANCg0KDQojIyBGb29kd2VicywgT3ZlcmxhcHBpbmcgey50YWJzZXR9DQojIyMgMQ0KYGBge3IgZ2FsbGVyeTF9DQppIDwtIDENCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMg0KYGBge3IgZ2FsbGVyeTJ9DQppIDwtIDINCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMw0KYGBge3IgZ2FsbGVyeTN9DQppIDwtIDMNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgNA0KYGBge3IgZ2FsbGVyeTR9DQppIDwtIDQNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgNQ0KYGBge3IgZ2FsbGVyeTV9DQppIDwtIDUNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgNg0KYGBge3IgZ2FsbGVyeTZ9DQppIDwtIDYNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgNw0KYGBge3IgZ2FsbGVyeTd9DQppIDwtIDcNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgOA0KYGBge3IgZ2FsbGVyeTh9DQppIDwtIDgNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KIyMgRm9vZHdlYnMsIExhcmdlciBGb29kIFByZWZlcmVuY2Ugey50YWJzZXR9DQojIyMgOQ0KYGBge3IgZ2FsbGVyeTl9DQppIDwtIDkNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMTANCmBgYHtyIGdhbGxlcnkxMH0NCmkgPC0gMTANCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMTENCmBgYHtyIGdhbGxlcnkxMX0NCmkgPC0gMTENCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMTINCmBgYHtyIGdhbGxlcnkxMn0NCmkgPC0gMTINCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMTMNCmBgYHtyIGdhbGxlcnkxM30NCmkgPC0gMTMNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMTQNCmBgYHtyIGdhbGxlcnkxNH0NCmkgPC0gMTQNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMTUNCmBgYHtyIGdhbGxlcnkxNX0NCmkgPC0gMTUNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMTYNCmBgYHtyIGdhbGxlcnkxNn0NCmkgPC0gMTYNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMTcNCmBgYHtyIGdhbGxlcnkxN30NCmkgPC0gMTcNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMTgNCmBgYHtyIGdhbGxlcnkxOH0NCmkgPC0gMTgNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0KDQojIyMgMTkNCmBgYHtyIGdhbGxlcnkxOX0NCmkgPC0gMTkNCnRvUG9zdE1vcnRlbShmb29kV2Vic1tbaV1dLCBub2RlU2l6ZSA9ICJOb25lIiwgdGhyZXNob2xkID0gIkFkYXB0aXZlIikgLT4gdGVtcA0KYGBgDQpgYGB7cn0NCnRlbXANCmBgYA0K